package com.heima.comment.service.impl;

import com.heima.aliyun.GreenTextScan;
import com.heima.comment.mapper.AdSensitiveMapper;
import com.heima.comment.service.CommentHotService;
import com.heima.comment.service.CommentService;
import com.heima.common.exception.CustomException;
import com.heima.feigns.UserFeign;
import com.heima.model.comment.dtos.CommentDto;
import com.heima.model.comment.dtos.CommentSaveDto;
import com.heima.model.comment.pojos.ApComment;
import com.heima.model.comment.pojos.ApCommentLike;
import com.heima.model.comment.vos.ApCommentVo;
import com.heima.model.common.dtos.CommentLikeDto;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.threadlocal.AppThreadLocalUtils;
import com.heima.model.user.pojos.ApUser;
import com.heima.utils.common.SensitiveWordUtil;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

@Service
@Slf4j
public class CommentServiceImpl implements CommentService {
    @Autowired
    private UserFeign userFeign;
    @Autowired
    private AdSensitiveMapper adSensitiveMapper;
    @Autowired
    private GreenTextScan greenTextScan;
    @Autowired
    private MongoTemplate mongoTemplate;
    @Autowired
    private CommentHotService commentHotService;
    @Autowired
    private RedissonClient redisson;

    /**
     * 保存评论
     */
    @Override
    public ResponseResult saveComment(CommentSaveDto dto) {
        //获取用户登录状态
        ApUser user = AppThreadLocalUtils.getUser();
        if (user == null || user.getId() == null) {
            CustomException.cust(AppHttpCodeEnum.NEED_LOGIN);
        }
        //判断评论的内容是否带有敏感词
        String content = dto.getContent();
        Boolean s = sensitiveContentFilter(content);
        if (!s) {
            CustomException.cust(AppHttpCodeEnum.DATA_NOT_ALLOW, "包含有敏感词！！！");
        }
        //获取当前用户信息
        ResponseResult res = userFeign.findUserById(user.getId());
        if (res.getCode() != 0 || res.getData() == null) {
            log.info("articleFeign 远程调用 findAuthorByUserId出错！");
            CustomException.cust(AppHttpCodeEnum.REMOTE_SERVER_ERROR);
        }
        ApUser apUser = (ApUser) res.getData();
        //保存评论信息
        ApComment apComment = new ApComment();
        apComment.setAuthorId(apUser.getId());
        apComment.setAuthorName(apUser.getName());
        apComment.setImage(apUser.getImage());
        apComment.setContent(dto.getContent());
        apComment.setArticleId(dto.getArticleId());
        apComment.setCreatedTime(new Date());
        apComment.setUpdatedTime(new Date());
        apComment.setLikes(0);
        apComment.setReply(0);
        apComment.setType((short) 0);
        apComment.setFlag((short) 0);
        mongoTemplate.save(apComment);
        return ResponseResult.okResult();
    }

    /**
     * 保存评论点赞
     */
    @Override
    public ResponseResult like(CommentLikeDto dto) {
        //检查用户登录状态
        //压力测试
        ApUser user = AppThreadLocalUtils.getUser();
        if (user == null || user.getId() == null) {
            CustomException.cust(AppHttpCodeEnum.NEED_LOGIN);
        }
        Integer uid = user.getId();
//        Integer uid = 4;
        String commentId = dto.getCommentId();
        Short operation = dto.getOperation();
        //查看当前评论跟评论id是否能够对应起来
        RLock rLock = redisson.getLock("likes-lock");
        rLock.lock();
        ApComment apComment;
        try {
            apComment = mongoTemplate.findById(commentId, ApComment.class);
            if (apComment == null) {
                CustomException.cust(AppHttpCodeEnum.DATA_NOT_EXIST, "当前评论不存在呦！");
            }
            //用户不能重复点赞
            Query query = Query.query(Criteria
                    .where("commentId").is(commentId)
                    .and("authorId").is(uid));
            //压力测试 注释掉
            ApCommentLike apCommentLike = mongoTemplate.findOne(query, ApCommentLike.class);
            if (apCommentLike != null && operation == 0) {
                CustomException.cust(AppHttpCodeEnum.DATA_NOT_ALLOW, "你已经点过赞啦！");
            }
            if (apCommentLike == null && operation == 1) {
                CustomException.cust(AppHttpCodeEnum.DATA_NOT_ALLOW, "你还没有点过赞呢");
            }
            if (operation == 0) {
                //保存点赞行为
                apComment.setLikes(apComment.getLikes() + 1);
                mongoTemplate.save(apComment);
                //判断当前操作之后是否会变成热点评论
                if (apComment.getLikes() >= 10 && apComment.getFlag() == 0) {
                    commentHotService.hotCommentExecutor(apComment);
                }
                //保存评论点赞信息
                apCommentLike = new ApCommentLike();
                apCommentLike.setAuthorId(uid);
                apCommentLike.setCommentId(apComment.getId());
                apCommentLike.setOperation((short) 0);
                mongoTemplate.save(apCommentLike);
            } else {
                //取消点赞
                apComment.setLikes(apComment.getLikes() - 1);
                //判断是否会影响热点评论
                if (apComment.getFlag() == 1 && apComment.getLikes() < 10) {
                    apComment.setFlag((short) 0);
                }
                mongoTemplate.save(apComment);
                //删除关联关系
                Query cancelQuery = Query.query(Criteria
                        .where("authorId").is(uid)
                        .and("commentId").is(apComment.getId()));
                mongoTemplate.remove(cancelQuery, ApCommentLike.class);
            }
        } finally {
            rLock.unlock();
        }
        HashMap<String, Object> map = new HashMap<>();
        map.put("likes", apComment.getLikes());
        return ResponseResult.okResult(map);
    }

    /**
     * 查看评论列表
     */
    @Override
    public ResponseResult commentViews(CommentDto dto) {
        //初始化分页查询的条件
        if (dto.getMinDate() == null) {
            dto.setMinDate(new Date());
        }
        if (dto.getSize() == null || dto.getSize() < 1) {
            dto.setSize(10);
        }
        //获取当前用户的登录状态
        ApUser user = AppThreadLocalUtils.getUser();
        List<ApComment> apComments = new ArrayList<>();//返回集合

        //如果是首页则先查询所有的热点评论，然后拼接集合
        if (dto.getIndex() == 1) {
            Query hotQuery = Query.query(Criteria
                    .where("articleId").is(dto.getArticleId())
                    .and("flag").is(1))//所有热点文章
                    .with(Sort.by(Sort.Direction.DESC, "likes"));
            List<ApComment> hotApComments = mongoTemplate.find(hotQuery, ApComment.class);
            int size = dto.getSize() - hotApComments.size();
            List<ApComment> normalApComments = mongoTemplate.find(getQuery(dto, size), ApComment.class);
            apComments.addAll(hotApComments);
            apComments.addAll(normalApComments);
        } else {
            //不是首页则查询所有的非热点评论
            apComments = mongoTemplate.find(getQuery(dto, dto.getSize()), ApComment.class);
        }
        //用户未登录则直接返回封装结果
        if ((user == null || user.getId() == null) && dto.getIndex() == 1) {
            return ResponseResult.okResult(apComments);
        }
        //用户已登录则将用户的点赞评论信息封装返回
        //获取所有的文章id
        List<String> commentList = apComments.stream().map(apComment -> apComment.getId()).collect(Collectors.toList());
        //根据文章id集合以及当前用户的id查询被点过赞的评论
        Query likesQuery = Query.query(Criteria
                .where("commentId").in(commentList)
                .and("authorId").is(user.getId()));
        List<ApComment> likeCommentList = mongoTemplate.find(likesQuery, ApComment.class);
        //获取所有被点过赞的评论的id
        List<String> likesCommentIds = likeCommentList.stream().map(apComment -> apComment.getId()).collect(Collectors.toList());
        //封装返回消息
        ArrayList<ApCommentVo> apCommentVos = new ArrayList<>();
        apComments.forEach(apComment -> {
            ApCommentVo commentVo = new ApCommentVo();
            BeanUtils.copyProperties(apComment, commentVo);
            if (likesCommentIds.contains(apComment.getId())) {
                //说明当前评论被点过赞
                commentVo.setOperation((short) 0);
            }
            apCommentVos.add(commentVo);
        });
        return ResponseResult.okResult(apCommentVos);
    }

    /**
     * 评论敏感词过滤
     */
    public Boolean sensitiveContentFilter(String content) {
        //获取所有敏感词
        List<String> allSensitives = adSensitiveMapper.findAllSensitives();
        //本地维护的敏感词审核
        SensitiveWordUtil.initMap(allSensitives);
        Map<String, Integer> matchWords = SensitiveWordUtil.matchWords(content);
        if (matchWords.size() > 0) {
            return false;
        }
        //远程调用阿里云接口审核
        try {
            Map map = greenTextScan.greenTextScan(content);
            String suggestion = (String) map.get("suggestion");
            if (suggestion.equals("pass")) {
                return true;
            }
            return false;
        } catch (Exception e) {
            e.printStackTrace();
            CustomException.cust(AppHttpCodeEnum.REMOTE_SERVER_ERROR, "阿里云调用出错");
            return false;
        }
    }


    /**
     * 获取查询条件
     */
    private Query getQuery(CommentDto dto, Integer size) {
        //根据size查询非热点文章
        Query query = Query.query(Criteria
                .where("articleId").is(dto.getArticleId())
                .and("createdTime").lt(dto.getMinDate())
                .and("flag").is(0))//所有非热点文章
                .limit(size)
                .with(Sort.by(Sort.Direction.DESC, "createdTime"));
        return query;
    }
}